Writing custom common controls

FastReport contains a set of common controls, which can be placed on the dialogue form inside a report. They are the following elements:

TfrxLabelControl

TfrxEditControl

TfrxMemoControl

TfrxButtonControl

TfrxCheckBoxControl

TfrxRadioButtonControl

TfrxListBoxControl

TfrxComboBoxControl

TfrxDateEditControl

TfrxBevelControl

TfrxPanelControl

TfrxGroupBoxControl

TfrxBitBtnControl

TfrxSpeedButtonControl

TfrxMaskEditControl

TfrxCheckListBoxControl

These elements correspond to the standard controls of the Delphi component palette. If standard functionality does not satisfy you, you can create your own common control and use it in your reports.

The basic class for all common controls is the TfrxDialogControl class described in the frxClass file:

TfrxDialogControl = class (TfrxReportComponent)

protected

procedure InitControl(AControl: TControl);

public

constructor Create(AOwner: TComponent); override ;

destructor Destroy; override ;

class function GetDescription: String ; virtual ;

property Caption: String ;

property Color: TColor;

property Control: TControl;

property OnClick: TfrxNotifyEvent;

property OnDblClick: TfrxNotifyEvent;

property OnEnter: TfrxNotifyEvent;

property OnExit: TfrxNotifyEvent;

property OnKeyDown: TfrxKeyEvent;

property OnKeyPress: TfrxKeyPressEvent;

property OnKeyUp: TfrxKeyEvent;

property OnMouseDown: TfrxMouseEvent;

property OnMouseMove: TfrxMouseMoveEvent;

property OnMouseUp: TfrxMouseEvent;

published

property Left;

property Top;

property Width;

property Height;

property Font;

property ParentFont;

property Enabled: Boolean;

property Visible;

end;

To create your own element, you should inherit from this class and override at least the constructor and the “GetDescription” methods. It will be necessary to create a common control and initialize it via the “InitControl” method in the constructor. The GetDescription method is to return the description of the common control. As you can see from the TfrxDialogControl class's description, it already contains a huge number of properties and methods in the public section. You need to transfer the necessary properties/events into the “published” section of your common control, and also to create new properties, which are typical for your element.

Registration and deleting of the common control is performed with the help of the frxObjects global object's methods declared in the frxDsgnIntf file:

frxObjects.RegisterObject(ClassRef: TfrxComponentClass; ButtonBmp:

TBitmap; const CategoryName: String = '');

frxObjects.Unregister(ClassRef: TfrxComponentClass);

During registration, you should specify control class' name, its picture, and the name of a category, to which it should be placed. If the name of a category is not specified, the control is placed in the basic component palette. The ButtonBmp size should be 22x22 pixels.

Categories allow grouping the objects' pictures in the toolbar, according to their functions. The categories are also used for saving space in the toolbar, since its size is limited. Nevertheless, it can contain a large number of objects.

To register a category, use the following method of the “frxObjects” object described in the “frxDsgnIntf” file:

frxObjects.RegisterCategory( const CategoryName: String ; ButtonBmp:

TBitmap; const ButtonHint: String ; ImageIndex: Integer = -1);

The first parameter is the name of a category. This name is used for identification of the category only and does not appear anywhere else. It should also be used when calling the “frxObjects.RegisterObject” procedure, if you want to place the registered object inside the given category. The second parameter is a picture; its size is 22x22 pixels. The third parameter is the category's description; it is displayed as a hint, if the button with a category is selected by the cursor.

Let us examine an example of the common control, which realizes simplified functionality of the standard Delphi TBitBtn control.

uses frxClass, frxDsgnIntf, Buttons;

type

TfrxBitBtnControl = class (TfrxDialogControl)

private

FButton: TBitBtn;

procedure SetKind( const Value: TBitBtnKind);

function GetKind: TBitBtnKind;

public

constructor Create(AOwner: TComponent); override ;

class function GetDescription: String; override ;

property Button: TBitBtn read FButton;

published

{ add new properties }

property Kind: TBitBtnKind read GetKind write SetKind default bkCustom;

{ these properties are already declared in the parent class }

property Caption;

property OnClick;

property OnEnter;

property OnExit;

property OnKeyDown;

property OnKeyPress;

property OnKeyUp;

property OnMouseDown;

property OnMouseMove;

property OnMouseUp;

end ;

constructor TfrxBitBtnControl.Create(AOwner: TComponent);

begin

{ default constructor }

inherited ;

{ create the required common control }

FButton := TBitBtn.Create( nil );

FButton.Caption := 'BitBtn';

{ initialize it }

InitControl(FButton);

{ it will have such size by default }

Width := 75;

Height := 25;

end;

class function TfrxBitBtnControl.GetDescription: String ;

begin

Result := 'BitBtn control';

end;

procedure TfrxBitBtnControl.SetKind( const Value: TBitBtnKind);

begin

FButton.Kind := Value;

end;

function TfrxBitBtnControl.GetKind: TBitBtnKind;

begin

Result := FButton.Kind;

end;

var

Bmp: TBitmap;

initialization

Bmp := TBitmap.Create;

{Load a picture from a resource. Of course, you should beforehand place it there.}

Bmp.LoadFromResourceName(hInstance, 'frxBitBtnControl');

frxObjects.RegisterObject(TfrxBitBtnControl, Bmp);

finalization

frxObjects.Unregister(TfrxBitBtnControl);

Bmp.Free;

end.